package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RedisIDWorker;
import com.hmdp.utils.SimpleRedisLock;
import com.hmdp.utils.UserHolder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
    @Resource
    private ISeckillVoucherService seckillVoucherService;
    @Resource
    private RedisIDWorker redisIDWorker;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedissonClient redissonClient;

    @Override/*优惠券秒杀*/
    public Result seckillVoucher(Long voucherId) {
//        查询优惠券信息
        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
//        判断秒杀是否开始
        if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
            /*尚未开始，返回错误信息*/
            return Result.fail("秒杀尚未开始！");
        }
        if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
            /*秒杀已结束*/
            return Result.fail("秒杀已结束!");
        }
        Long userId = UserHolder.getUser().getId();
//        SimpleRedisLock redisLock = new SimpleRedisLock("shop:" + userId, stringRedisTemplate);
        RLock redisLock = redissonClient.getLock("lock:order:" + userId);
        boolean isLock = redisLock.tryLock();/*无参为重试不等待*/
        if (!isLock) {
//            获取锁失败，返回错误或重试
            return Result.fail("不允许重复下单！");
        }
        try {
            /*必须调用当前代理对象才可以使用Spring的Transaction事物功能*/
            IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
            return proxy.createVoucherOrder(voucherId);
        } finally {
            /*释放锁*/
//            redisLock.unLock();
            redisLock.unlock();
        }

    }

    @Transactional
    public Result createVoucherOrder(Long voucherId) {
        //        一人一单
        Long userId = UserHolder.getUser().getId();

        Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
        if (count > 0) {
            return Result.fail("您已经领取过一次啦！");
        }

        /*扣减库存*/ /*在更新数据库时，再次比对stock库存数，CAS（CompareAndSwap）*/
        boolean success = seckillVoucherService.update().setSql("stock = stock - 1")
                .eq("voucher_id", voucherId).gt("stock", 0).update();
        /*关注点应该在库存数量是否大于0，只有在等于0时才不更新*/
        if (!success) {
            return Result.fail("库存不足！");
        }
//        创建订单
        VoucherOrder voucherOrder = new VoucherOrder();
        VoucherOrder orderId = voucherOrder.setId(redisIDWorker.nextId("order"));/*设置订单ID*/
        voucherOrder.setVoucherId(voucherId);/*代金券Id*/
        voucherOrder.setUserId(userId);
//        存入数据库并返回订单id
        save(voucherOrder);
        return Result.ok(orderId);
    }

}
